package com.os.crm.service;

import com.alibaba.fastjson.JSONObject;
import com.os.crm.mapper.DataTaskMapper;
import com.os.crm.mapper.RegionMapper;
import com.os.crm.pojo.DataSaveResult;
import com.os.crm.pojo.DataTask;
import com.os.crm.pojo.Enterprise;
import com.os.crm.pojo.Region;
import com.os.crm.pojo.baidu.BaiduMapDTO;
import com.os.crm.pojo.baidu.BaiduMapResult;
import com.os.crm.pojo.gaode.GaoDeMapDTO;
import com.os.crm.pojo.gaode.GaoDeMapResult;
import com.os.util.Tools;
import entity.Param;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GaoDeMapService {
    @Autowired
    EnterpriseService enterpriseService;
    @Autowired
    DataTaskService dataTaskService;
    @Autowired
    DataTaskMapper dataTaskMapper;
    @Autowired
    RegionService regionService;
    @Autowired
    RegionMapper regionMapper;

    public static final int pageSize = 50 ;

    public static String AK = "aba08ac19d513bce6cb5effecf0c346e";

    public static void main(String[] args){
        //System.out.println(Tools.getTimeNow().substring(0,10));
        //new BaiduMapService().getBaiduMapData(null, "烧烤", null);
        //System.out.println(generateLocationList("126.660","45.759"));
        new GaoDeMapService().getCityLocation();
    }

    /**
     * 获取所有行业区划的坐标（经度，纬度）
     */
    public void getCityLocation(){
        Map map = new HashMap();
        List paramList = new ArrayList();
        paramList.add(new Param("", " region_level IN (1, 2, 3) AND region_name !='市辖区' AND region_name!='县' \n" +
                "AND region_name NOT LIKE '%本级%'  ", "expr","",""));
        map.put("condstr", Tools.genCondStr("", paramList));
        List<Region> regionList = regionMapper.selectByParam(map);
        for(int i=0; i<regionList.size() ; i++){
            Region region = regionList.get(i);
            if(!StringUtils.isEmpty(region.getRegion_comment())){
                continue;
            }
            String url = "https://restapi.amap.com/v3/geocode/geo?key="+AK
                    +"&address="+region.getRegion_name() +"&city=";
            try {
                Thread.sleep(50);
            }catch (Exception e){

            }
            String str = loadJSON(url);
            GaoDeMapResult mapResult = JSONObject.parseObject(str, GaoDeMapResult.class);
            List<GaoDeMapDTO> geocodesList =  mapResult.getGeocodes();
            if(geocodesList==null){
                continue;
            }
            if(geocodesList.size()>0){
                String location = geocodesList.get(0).getLocation();
                region.setRegion_comment(location);
                regionMapper.updateByPrimaryKeySelective(region);
            }
        }

    }

    public void getMapData(){
        DataSaveResult dataSaveResult = new DataSaveResult();
        Map<String,Object> map = new HashMap<>();
        map.put("condstr","");
        List<DataTask> dataTaskList = dataTaskMapper.selectByParam(map);
        String dateNow = Tools.getDateNow();
        for(int i=0; i<dataTaskList.size(); i++){
            DataTask dataTask = dataTaskList.get(i);
            String startTime = Tools.getTimeNow();
            log.info("处理采集任务：" + dataTask.toString());
            String endTime = dataTask.getEnd_time();
            //如果今天已执行过了，则不执行该任务
            if(!StringUtils.isEmpty(endTime)){
                String endDate = endTime.substring(0,10);
                if(dateNow.equalsIgnoreCase(endDate)){
                    log.info("今天已执行过任务，任务执行结束");
                    continue;
                }
            }
            //执行定时任务
            //解析关键字
            String keyWord = dataTask.getKeyword();
            String location = dataTask.getLocation();
            if(StringUtils.isEmpty(keyWord) || StringUtils.isEmpty(location)){
                log.info("未指定关键字或坐标，不能执行数据采集");
                continue;
            }
            List<String> keyWordList = Arrays.asList(keyWord.split(",")).stream().filter(v -> !StringUtils.isEmpty(v)).collect(Collectors.toList());
            for(int j=0; j<keyWordList.size(); j++){
                DataSaveResult dataSaveResultTemp = getMapData(dataTask.getRegion_name(), keyWordList.get(j), location);
                addDataSaveResult(dataSaveResult, dataSaveResultTemp);
            }
            String end_time = Tools.getTimeNow();
            //更新任务完成时间
            dataTask.setStart_time(startTime);
            dataTask.setEnd_time(end_time);
            dataTask.setInsert_count(dataSaveResult.getInsertCount());
            dataTask.setUpdate_count(dataSaveResult.getUpdateCount());
            dataTaskMapper.updateByPrimaryKeySelective(dataTask);
        }
    }
    /**
     * 爬取数据存入数据库
     * @param cityName 查询区域
     * @param word 查询关键词
     * @param location 坐标位置
     * @return json字符串
     */
    public DataSaveResult getMapData(String cityName, String word, String location) {
        log.info("本次采集数据 参数：cityName："+cityName+",word="+word+",location="+location);
        String location_lng = "";
        String location_lat = "";
        if(!StringUtils.isEmpty(location)){
            String[] arr = location.split(",");
            String result = arr[1]+","+arr[0];
            location = result;
            location_lng = arr[1] ;
            location_lat = arr[0] ;
        }
        DataSaveResult dataSaveResult = new DataSaveResult();
//        if(StringUtils.isEmpty(cityName)){
//            location = "45.759,126.660";
//        }
        if(StringUtils.isEmpty(cityName) && StringUtils.isEmpty(location)){
            return dataSaveResult;
        }
        if(StringUtils.isEmpty(word) ){
            return dataSaveResult;
        }
        Integer code = 131;
        JSONObject obj = null;


        //按城市处理
        for (int i = 0; i < 10; i++) {
            String url = "http://api.map.baidu.com/place/v2/search?query=" + word + "&tag=&scope=2®ion=" + code
                    + "&output=json&page_size=10&page_num=" + i + "&ret_coordtype=gcj02ll&ak="+AK;
            url = "https://restapi.amap.com/v3/place/text?key="+AK+"&keywords="+word
                    +"&types=&city="+cityName+"&children=1&offset="+pageSize+"&page="+(i+1)+"&extensions=base";
            try {
                Thread.sleep(1000);
            }catch (Exception e){

            }
            String str = loadJSON(url);
            GaoDeMapResult mapResult = JSONObject.parseObject(str, GaoDeMapResult.class);
            DataSaveResult dataSaveResultTemp = saveMapResult(mapResult, word);
            addDataSaveResult(dataSaveResult, dataSaveResultTemp);
            int num = (i+1)*pageSize ;
            if(num > mapResult.getCount()){
                break;
            }
        }
        List<String> locationList = generateLocationList(location_lng, location_lat);
        for(int i=0; i<locationList.size(); i++){
            getMapDataByLocation(word, dataSaveResult, AK, locationList.get(i));
        }
        log.info("本次采集数据：新增："+dataSaveResult.getInsertCount()+"条，更新："+dataSaveResult.getUpdateCount()+"条。");
        return dataSaveResult;
    }

    public static List<String> generateLocationList(String location_lng, String location_lat){
        Double offSet = 0.3 ;
        Double offSet45 = 0.2 ; //45度角位移量
        Double lngDouble = Double.valueOf(location_lng);
        Double latDouble = Double.valueOf(location_lat);
        String location0 = location_lng +"," + location_lat;
        String location1 = location_lng +"," + (latDouble+offSet);
        String location2 = location_lng +"," + (latDouble - offSet);
        String location3 = (lngDouble + offSet) +"," + location_lat;
        String location4 = (lngDouble - offSet) +"," + location_lat;

        String location5 =  (lngDouble + offSet45) +"," + (latDouble + offSet45);
        String location6 =  (lngDouble - offSet45) +"," + (latDouble - offSet45);
        String location7 =  (lngDouble + offSet45) +"," + (latDouble - offSet45);
        String location8 =  (lngDouble - offSet45) +"," + (latDouble + offSet45);

        List<String> locationList = new ArrayList<>();
        locationList.add(location0); //当前中心点
        locationList.add(location1);
        locationList.add(location2);
        locationList.add(location3);
        locationList.add(location4);
        locationList.add(location5);
        locationList.add(location6);
        locationList.add(location7);
        locationList.add(location8);
        return locationList ;
    }

    private void getMapDataByLocation(String word, DataSaveResult dataSaveResult, String AK, String location) {
        if(StringUtils.isEmpty(location)){
            return;
        }
        //按坐标处理
        for (int i = 0; i < 10; i++) {
            String url = "https://restapi.amap.com/v3/place/around?key="+AK+"&location="+location+"&keywords="+word+"&types=&radius=20000&offset="+pageSize+"&page="+(i+1)+"&extensions=base";
            try {
                Thread.sleep(1000);
            }catch (Exception e){
            }
            String str = loadJSON(url);
            GaoDeMapResult mapResult = JSONObject.parseObject(str, GaoDeMapResult.class);
            DataSaveResult dataSaveResultTemp = saveMapResult(mapResult, word);
            addDataSaveResult(dataSaveResult, dataSaveResultTemp);
            int num = (i+1)*pageSize ;
            if(num > mapResult.getCount()){
                break;
            }
        }
    }

    private void addDataSaveResult(DataSaveResult dataSaveResultTotal, DataSaveResult dataSaveResultTemp){
        dataSaveResultTotal.setInsertCount(dataSaveResultTotal.getInsertCount() + dataSaveResultTemp.getInsertCount());
        dataSaveResultTotal.setUpdateCount(dataSaveResultTotal.getUpdateCount() + dataSaveResultTemp.getUpdateCount());
    }

    public DataSaveResult saveMapResult(GaoDeMapResult baiduMapResult, String word){
        List<Enterprise> enterpriseList = new ArrayList<>();
        List<GaoDeMapDTO> mapDTOList = baiduMapResult.getPois();
        int insertCount = 0;
        int updateCount = 0;
        DataSaveResult dataSaveResult = new DataSaveResult();
        if(!CollectionUtils.isEmpty(mapDTOList)){
            for(int i=0; i< mapDTOList.size(); i++){
                GaoDeMapDTO gaoDeMapDTO = mapDTOList.get(i);
                Enterprise enterprise = new Enterprise();
                BeanUtils.copyProperties(gaoDeMapDTO, enterprise);
                enterprise.setSource_type("高德地图");
                enterprise.setEnt_name(gaoDeMapDTO.getName());
                enterprise.setArea_name(gaoDeMapDTO.getAdname());
                enterprise.setCity_name(gaoDeMapDTO.getCityname());
                enterprise.setProvince_name(gaoDeMapDTO.getPname());
                String location = gaoDeMapDTO.getLocation();
                String[] locationArr = location.split(",");
                enterprise.setLocation_lng(locationArr[0]);
                enterprise.setLocation_lat(locationArr[1]);
                enterprise.setEnt_comment(gaoDeMapDTO.getId());
                enterprise.setPhone(gaoDeMapDTO.getTel());
                enterprise.setBusiness_name(word);
                enterpriseList.add(enterprise);
                log.info("enterprise=", enterprise);
                //System.out.println(enterprise);

                //依赖容器
                int saveType = enterpriseService.save(enterprise);
                if(saveType == EnterpriseService.SAVE_TYPE_INSERT){
                    insertCount++;
                }
                if(saveType == EnterpriseService.SAVE_TYPE_UPDATE){
                    updateCount++;
                }
            }
        }
        dataSaveResult.setInsertCount(insertCount);
        dataSaveResult.setUpdateCount(updateCount);
        return dataSaveResult;
    }

    /**
     * 根据地址(url)获取页面数据
     * @param uri
     * @return
     */
    public String loadJSON (String uri) {
        StringBuilder json = new StringBuilder();
        try {
            URL url = new URL(uri);
            URLConnection yc = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"utf-8"));
            String inputLine = null;
            while ( (inputLine = in.readLine()) != null) {
                json.append(inputLine);
            }
            in.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return json.toString();
    }
}
